import sys
import re
import os
import win32com.client
import time
from sets import Set
from Helpers import DebugObj
from Settings import Settings


class iTunesOrganizer:

  def __init__(self):
    self.iTunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
    self.offTheNetTracks = []
    self.totalSize = 0

  # Add a track to iTunes
  def __addOffTheNetTrack(self, track):
    self.offTheNetTracks.append(track)
    self.totalSize = self.totalSize + track.Size

  # Remove a track from iTunes and from the file system
  def __removeTrackFromItunes(self, track):
    size = track.Size
    location = track.Location
    track.Delete()
    os.remove(location)
    self.totalSize = self.totalSize - size

  # Loop through all the files in iTunes and find the ones
  # that are from the crawler  
  def __loadOffTheNetTracks(self):
    for track in self.iTunes.LibraryPlaylist.Tracks:
      if track.KindAsString == "MPEG audio file":
        if track.Location.startswith(Settings.BasePath):
          self.__addOffTheNetTrack(track)

  # Convert an array to a set
  def __loadSetFromList(self, offTheNetTracks):
    playlistSet = Set();
    for track in offTheNetTracks:
      playlistSet.add(track.Location)
    return playlistSet

  # Load the Off The Net files from the filsystem
  def __loadSetFromDirectory(self, directoryName):
    directorySet = Set()
    validFile = re.compile('.+\.(mp3|m4a|m4p)$')
    for root, dirs, files in os.walk(directoryName):
      if len(dirs):
        continue
      slen = len(directoryName)
      for file in files:
        m = validFile.match(file)
        if not  m:
          continue
        path = root + "\\" + file
        directorySet.add(path)
    return directorySet

  # Add the given array to iTunes  
  def __addNewFilesToPlaylist(self, filesToAdd):
    for file in filesToAdd:
      opstatus = self.iTunes.LibraryPlaylist.AddFile(file)
      if (opstatus != None):
        newTrack = win32com.client.CastTo(opstatus.Tracks[0], "IITFileOrCDTrack")
        DebugObj().write("Adding " + newTrack.Location)
        self.__addOffTheNetTrack(newTrack)
      else:
        DebugObj().write("Could not add %s.  Deleting it from the directory." % (file))
        os.remove(file)

  def __addNewTracksToPlaylist(self):
    playlistSet = self.__loadSetFromList(self.offTheNetTracks)
    directorySet = self.__loadSetFromDirectory(Settings.BasePath)
    self.__addNewFilesToPlaylist(directorySet.difference(playlistSet))

  def __purgeTracks(self):
    self.offTheNetTracks.sort(date_compare)
    for track in self.offTheNetTracks:
      if track.Comment != Settings.Comment:
        track.Comment = Settings.Comment
      toDelete = False
      if (track.Rating == 20):
        DebugObj().write("Deleting %s (because it has a low rating)" % track.Location)
        toDelete = True
      elif (track.Duration > 600):
        DebugObj().write("Deleting %s (because it is over 10 mins long)" % track.Location)
        toDelete = True
      elif (track.Rating >= 60):
        continue
      elif (self.totalSize > 4294967296):
        DebugObj().write("Deleting %s (because there are over %d bytes of songs)" % (track.Location, self.totalSize))
        toDelete = True
      if (toDelete == True):
        self.__removeTrackFromItunes(track)

  def run(self):
    self.__loadOffTheNetTracks()
    self.__addNewTracksToPlaylist()
    self.__purgeTracks()


def date_compare(x, y):
  if x.DateAdded>y.DateAdded:
    return 1
  elif x.DateAdded==y.DateAdded:
    return 0
  else: # x[1]<y[1]
    return -1


if __name__ == "__main__":
  start = time.time()
  ituneso = iTunesOrganizer()
  ituneso.run()
  end = time.time()
  runtime = end - start
  DebugObj().write("Runtime: %d secs" % (runtime))
